
apply :: (α -> α -> α) -> α -> α -> α
apply f a b = f a b

add :: Num α => α -> α -> α
add = apply (+)

sub :: Num α => α -> α -> α
sub = apply (-)


class Functor ϕ where
    fmap :: (α -> β) -> ϕ α -> ϕ β

fmap id = id
fmap (f . g) = fmap f . fmap g

class Monoid α where
    mempty :: α
    mappend :: α -> α -> α

mconcat :: Monoid α => [α] -> α
mconcat = foldl mappend mempty

type Node = Int
pmap = undefined
preduce = undefined
dmap = undefined
dreduce = undefined

pmap :: [Int] -> ([β] -> β) -> (α -> β) -> [α] -> [β]
pmap' :: (α -> β) -> [α] -> [β]
pmap' = pmap (repeat 1) head

preduce :: [Int] -> ([α] -> α) -> (α -> α -> α) -> [α] -> α
preduce' :: (α -> α -> α) -> [α] -> α
preduce' = preduce (repeat 1) head

dmap  :: [Int] -> ([β] -> β) -> [Node] -> (α -> β) -> [α] -> IO [β]
dmap' :: [Node] -> (α -> β) -> [α] -> IO [β]
dmap' = dmap (repeat 1) head

dreduce  :: [Int] -> ([β] -> β) -> [Node] -> (α -> α -> α) -> [α] -> IO α
dreduce' :: [Node] -> (α -> α -> α) -> [α] -> α
dreduce' = dreduce (repeat 1) head
